package com.aaa.worldmodel.surface;

import android.content.Context;
import android.graphics.Color;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.aaa.worldmodel.move.MoveManager;
import com.aaa.worldmodel.move.MovementListener;
import com.aaa.worldmodel.surface.model.Model;
import com.aaa.worldmodel.utils.LogUtils;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class WorldSurfaceView extends GLSurfaceView implements GLSurfaceView.Renderer {
    private static final float MAX_SCALE = 1024;
    private static final float MIN_SCALE = 1 / 1024f;
    final float TOUCH_SCALE_AC = 5;

    private int bgColor = Color.argb(1, 33, 162, 254);
    private float[] modelMatrix = Model.getOriginalMatrix();
    private float[] mProjMatrix = new float[16];
    private float[] mVMatrix = new float[16];
    private float[] light;
    private float rotateX = 0;
    private float rotateY = 0;
    private float scale = 1;
    private MoveManager moveManager;
    private TouchHandler touchHandler;
    private ModelManager modelManager;
    private boolean isCreate = false;

    public WorldSurfaceView(Context context) {
        super(context);
        init();
    }

    public WorldSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        setEGLContextClientVersion(3);
        setRenderer(this);
        setRenderMode(RENDERMODE_WHEN_DIRTY);

        touchHandler = new TouchHandler(this);
        moveManager = new MoveManager();
        moveManager.setMovementListener(new MovementListener() {
            @Override
            public void onMove(float positionX, float positionY, float positionZ, float directionX, float directionY, float directionZ) {
                LogUtils.i("position: (" + positionX + "," + positionY + "," + positionZ + ")");
                LogUtils.i("direction: (" + directionX + "," + directionY + "," + directionZ + ")");
            }
        });

        modelManager = new ModelManager();
        modelManager.setModelListener(new ModelListener() {
            @Override
            public void onModelAdd(final Model model) {
                //suface创建时 会将已添加的model全部执行一遍oncreate
                //surface创建之后添加的model才需要重新执行oncreate
                if (isCreate) {
                    queueEvent(new Runnable() {
                        @Override
                        public void run() {
                            model.onCreate(getContext());
                        }
                    });
                }
            }

            @Override
            public void onModelRemove(final Model model) {
                //移除model时销毁
                queueEvent(new Runnable() {
                    @Override
                    public void run() {
                        model.onDestroy();
                    }
                });
            }
        });


        light = new float[]{
                -1f, -1f, -1f,       // direction  x y z
                0.2f, 0.2f, 0.2f,   // ka
                0.8f, 0.8f, 0.8f,   // kd
                0.1f, 0.1f, 0.1f,   // ks
        };
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return touchHandler.onTouchEvent(event);
    }


    /**
     * 设置背景颜色
     *
     * @param color
     */
    public void setBackgroundColor(int color) {
        this.bgColor = color;
        float bgRed = Color.red(bgColor) / 255f;
        float bgGreen = Color.green(bgColor) / 255f;
        float bgBlue = Color.blue(bgColor) / 255f;
        float bgAlpha = Color.alpha(bgColor) / 255f;
        GLES30.glClearColor(bgRed, bgGreen, bgBlue, bgAlpha);
        requestRender();
    }


    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        setBackgroundColor(bgColor);
        GLES30.glEnable(GLES30.GL_DEPTH_TEST);
        GLES30.glEnable(GLES30.GL_CULL_FACE_MODE);
        modelManager.onCreate(getContext());
        isCreate = true;
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
        mVMatrix = moveManager.genViewMatrix();
        Matrix.perspectiveM(mProjMatrix, 0, 90, (width + 0f) / height, 0.1f, 100);

        modelManager.setMatrix(modelMatrix, mVMatrix, mProjMatrix);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
        modelManager.onDraw();
    }

    public void addModel(final Model model) {
        model.setMatrix(modelMatrix, mVMatrix, mProjMatrix);
        model.setEye(moveManager.getPosition());
        model.setLight(light);
        modelManager.addModel(model);
    }

    public void remove(Model model) {
        modelManager.removeModel(model);
    }

    public void clear() {
        modelManager.clear();
    }

    //旋转整个世界 当只有一个眼睛的时候等同 其实就相当于自己转....
    public void rotateWorld(float distanceX, float distanceY) {
        rotateX = rotateX + distanceX;
        rotateY = rotateY + distanceY;

        Matrix.setRotateM(modelMatrix, 0, -rotateY / TOUCH_SCALE_AC, 1, 0, 0);
        Matrix.rotateM(modelMatrix, 0, -rotateX / TOUCH_SCALE_AC, 0, 1, 0);
        Matrix.scaleM(modelMatrix, 0, scale, scale, scale);

        updateModel();
    }

    public void scale(float s) {
        //这样写可以造成一个缩放回弹的效果 回弹效果要在scaleEnd时重新设置回边界大小
        Matrix.scaleM(modelMatrix, 0, s, s, s);
        scale = scale * s;
        updateModel();
    }

    public void onScaleEnd(float s) {
        float tempScale = scale * s;
        LogUtils.i("scale end ");
        if (tempScale > MAX_SCALE) {
            s = MAX_SCALE / scale;
            scale = MAX_SCALE;
        } else if (tempScale < MIN_SCALE) {
            s = MIN_SCALE / scale;
            scale = MIN_SCALE;
        } else {
            scale = tempScale;
        }
        Matrix.scaleM(modelMatrix, 0, s, s, s);

        updateModel();
    }


    public void move(float distanceX, float distanceY, float distanceZ) {
        mVMatrix = moveManager.move(distanceX, distanceY, distanceZ);
        updateModel();
    }

    public void move(float distance) {
        mVMatrix = moveManager.moveDirection(distance);
        updateModel();
    }

    public void moveTo(float x, float y, float z) {
        mVMatrix = moveManager.moveTo(x, y, z);
        updateModel();
    }


    /**
     * 俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll)
     *
     * @param rotateX rotateY rotateZ
     */
    public void rotateSelf(float pitch, float yaw, float roll) {
        mVMatrix = moveManager.rotate(pitch, yaw, roll);
        updateModel();
    }

    private void updateModel() {
        modelManager.setMatrix(modelMatrix, mVMatrix, mProjMatrix);
        requestRender();
    }
}
